package com.gxitsky.common.exception;

import com.gxitsky.exception.BusinessException;
import com.gxitsky.response.ResponseModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileUploadException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @desc: 全局异常处理
 * @date: 2019/3/30 10:29
 **/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final String SINGLE_QUOTE_REGEX = "\\'[^\\']*\\'";

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResponseModel<?> defaultErrorHandler(HttpServletRequest req, Exception e) {
        log.error("----->统一异常处理:", e);

        if (e instanceof BusinessException) {
            return ResponseModel.fail(e);
        }

        if (e instanceof IllegalArgumentException) {
            return ResponseModel.methodArgException();
        }

        if (e instanceof MethodArgumentTypeMismatchException) {
            if (e.getCause() instanceof NumberFormatException) {
                return ResponseModel.methodArgNumberFormatException();
            }
            return ResponseModel.methodArgNumberFormatException();
        }

        if (e instanceof DuplicateKeyException) {
            //唯一索引重复
            String message = e.getCause().getMessage();
            if (message.startsWith("Duplicate entry")) {
                StringBuilder sb = new StringBuilder("字段: ");
                Pattern pattern = Pattern.compile(SINGLE_QUOTE_REGEX);
                Matcher match = pattern.matcher(message);
                //取第一个字段值
                if (match.find()) {
                    String group = match.group().replace("'", "");
                    sb.append(group).append(" 已存在,不可重复");
                }
                return ResponseModel.dbDuplicateKeyFail(sb.toString());
            }
            return ResponseModel.dbDuplicateKeyFail();
        }

        if (e instanceof NoHandlerFoundException) {
            //找不到处理器(访问的URI不存在)
            return ResponseModel.requestUirNotFound();
        }

        if (e instanceof HttpRequestMethodNotSupportedException) {
            //HTTP请求类型不支持
            return ResponseModel.requestMethodNotSupport();
        }

        if (e instanceof HttpMessageNotReadableException) {
            String message = e.getMessage();
            //越界
            if (message.contains("out of range")) {
                return ResponseModel.requestBodyLengthOutRange();
            }
            return ResponseModel.requestBodyNotReadable();
        }

        if (e instanceof HttpMediaTypeNotSupportedException) {
            //请求参数Content-Type错误
            return ResponseModel.requestContentTypeNotSupport();
        }

        if (e instanceof DataIntegrityViolationException) {
            //当尝试插入或更新数据导致违反完整性约束时引发异常, 表必填字段为空、超出表字段长度。
            return ResponseModel.dbDataIntegrityViolationException();
        }

        if (e instanceof MethodArgumentNotValidException) {
            //@Valid注解的参数校验异常
            BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
            if (bindingResult.hasErrors()) {
                List<ObjectError> errorList = bindingResult.getAllErrors();
                StringBuilder sb = new StringBuilder();
                for (ObjectError error : errorList) {
                    sb.append(error.getDefaultMessage()).append(";");
                }
                return ResponseModel.requestParamValidError(sb.toString());
            }
            return ResponseModel.requestParamValidError();
        }

        if (e instanceof FileUploadException) {
            // 文件上传异常
            return ResponseModel.FileUploadFail(e.getMessage());
        }

        if (e instanceof MaxUploadSizeExceededException) {
            // 上传的文件大小超出最大限制
            return ResponseModel.FileUploadSizeOutOfMax();
        }
        return ResponseModel.fail(new BusinessException(e.getMessage()));
    }
}